package com.jilijili.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.jilijili.config.mq.RabbitMQConfig;
import com.jilijili.enums.MessageEnum;
import com.jilijili.enums.YesOrNo;
import com.jilijili.exceptions.GraceException;
import com.jilijili.grace.result.ResponseStatusEnum;
import com.jilijili.mapper.MyLikedVlogMapper;
import com.jilijili.mapper.VlogMapper;
import com.jilijili.mapper.VlogMapperCustom;
import com.jilijili.pojo.Fans;
import com.jilijili.pojo.MyLikedVlog;
import com.jilijili.pojo.Users;
import com.jilijili.pojo.Vlog;
import com.jilijili.pojo.bo.VlogBo;
import com.jilijili.pojo.mo.MessageMo;
import com.jilijili.pojo.vo.IndexVlogVO;
import com.jilijili.service.FansService;
import com.jilijili.service.MsgService;
import com.jilijili.service.VlogService;
import com.jilijili.service.base.BaseInfoProperties;
import com.jilijili.service.base.PagedGridResult;
import com.jilijili.utils.redis.RedisOperator;
import org.n3r.idworker.Sid;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author admin
 * @description 针对表【vlog(短视频表)】的数据库操作Service实现
 * @createDate 2022-03-12 07:11:29
 */
@Service
public class VlogServiceImpl extends ServiceImpl<VlogMapper, Vlog> implements VlogService {

    @Resource
    private VlogMapper vlogMapper;

    @Resource
    private VlogMapperCustom vlogMapperCustom;

    @Resource
    private FansService fansService;

    @Resource
    private MyLikedVlogMapper myLikedVlogMapper;

    @Resource
    private MsgService msgService;

    @Resource
    private RedisOperator redis;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private Sid sid;


    /**
     * 把counts输入到数据库中
     *
     * @param vlogId
     * @param counts
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public void flushCounts(String vlogId, Long counts) {
        Vlog vlog = Vlog.builder()
                .id(vlogId)
                .likeCounts(Math.toIntExact(counts)).build();
        int ifUpdate = this.vlogMapper.updateById(vlog);
        if (ifUpdate < 0) {
            GraceException.display(ResponseStatusEnum.FAILED);
        }
    }


    /**
     * 我朋友的列表
     */
    @Override
    public PagedGridResult getMyFriendVlogList(String myId, Integer page, Integer pageSize) {
        IPage<IndexVlogVO> indexVlogVOIPage = this.vlogMapper.selectJoinPage(new Page<IndexVlogVO>(page, pageSize), IndexVlogVO.class, new MPJLambdaWrapper<IndexVlogVO>().selectAs(Vlog::getId, IndexVlogVO::getVlogId).selectAs(Vlog::getVlogerId, IndexVlogVO::getVlogerId).selectAs(Users::getFace, IndexVlogVO::getVlogerFace).selectAs(Users::getNickname, IndexVlogVO::getVlogerName).selectAs(Vlog::getTitle, IndexVlogVO::getContent).selectAs(Vlog::getLikeCounts, IndexVlogVO::getLikeCounts).selectAs(Vlog::getCommentsCounts, IndexVlogVO::getCommentsCounts).selectAs(Vlog::getIsPrivate, IndexVlogVO::getIsPrivate).select(Vlog::getCover, Vlog::getUrl, Vlog::getWidth, Vlog::getHeight).leftJoin(Fans.class, Fans::getFanId, Vlog::getVlogerId).leftJoin(Users.class, Users::getId, Fans::getFanId).eq(true, Fans::getVlogerId, myId).and(true, (lambdaWrapper) -> lambdaWrapper.eq(true, Vlog::getIsPrivate, YesOrNo.NO.type)).and(true, (lambdaWrapper) -> lambdaWrapper.eq(true, Fans::getIsFanFriendOfMine, YesOrNo.YES.type)).orderBy(true, false, Vlog::getCreatedTime));

        // 判斷是否有點讚的視頻
        if (StringUtils.isNotBlank(myId)) {
            List<IndexVlogVO> records = indexVlogVOIPage.getRecords();
            for (IndexVlogVO item : records) {
                String vlogerId = item.getVlogerId();
                String vlogId = item.getVlogId();

                // 查詢判斷用戶點讚過的視頻
                String boole = this.redis.get(BaseInfoProperties.REDIS_USER_LIKE_VLOG + ":" + myId + ":" + vlogId);
                item.setDoILikeThisVlog(!StringUtils.isBlank(boole) && "1".equalsIgnoreCase(boole));

                boolean b = fansService.queryDoIFollowVloger(myId, vlogerId);
                item.setDoIFollowVloger(b); // 必定是true,我關注的博主列表

                // 查詢視頻的點讚總數
                String vlogLikeCount = this.redis.getStr(BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
                if (StringUtils.isNotBlank(vlogLikeCount) && !vlogLikeCount.equalsIgnoreCase("null")) {
                    item.setLikeCounts(Integer.valueOf(vlogLikeCount));
                } else {
                    item.setLikeCounts(0);
                }
            }
            indexVlogVOIPage.setRecords(records);
        }

        /*Map<String,Object> map = new HashMap<>();
        map.put("myId",myId);
        List<IndexVlogVO> myFriendVlogList = this.vlogMapperCustom.getMyFriendVlogList(map);*/

        PagedGridResult pagedGridResult = new PagedGridResult();
        pagedGridResult.setRows(indexVlogVOIPage.getRecords());
        pagedGridResult.setPage((int) indexVlogVOIPage.getCurrent());
        pagedGridResult.setTotal(indexVlogVOIPage.getPages());
        pagedGridResult.setRecords(indexVlogVOIPage.getTotal());
        return pagedGridResult;
    }

    /**
     * 我關注的博主視頻
     */
    @Override
    public PagedGridResult getMyFollowVlog(String myId, Integer page, Integer pageSize) {
        IPage<IndexVlogVO> indexVlogVOIPage = this.vlogMapper.selectJoinPage(new Page<IndexVlogVO>(page, pageSize), IndexVlogVO.class, new MPJLambdaWrapper<IndexVlogVO>().selectAs(Vlog::getId, IndexVlogVO::getVlogId).selectAs(Vlog::getVlogerId, IndexVlogVO::getVlogerId).selectAs(Users::getFace, IndexVlogVO::getVlogerFace).selectAs(Users::getNickname, IndexVlogVO::getVlogerName).selectAs(Vlog::getTitle, IndexVlogVO::getContent).selectAs(Vlog::getLikeCounts, IndexVlogVO::getLikeCounts).selectAs(Vlog::getCommentsCounts, IndexVlogVO::getCommentsCounts).selectAs(Vlog::getIsPrivate, IndexVlogVO::getIsPrivate).select(Vlog::getCover, Vlog::getUrl, Vlog::getWidth, Vlog::getHeight).leftJoin(Fans.class, Fans::getVlogerId, Vlog::getVlogerId).leftJoin(Users.class, Users::getId, Fans::getVlogerId).eq(true, Fans::getFanId, myId).and(true, (lambdaWrapper) -> lambdaWrapper.eq(true, Vlog::getIsPrivate, YesOrNo.NO.type)).orderBy(true, false, Vlog::getCreatedTime));
        // 判斷是否有點讚的視頻
        if (StringUtils.isNotBlank(myId)) {
            List<IndexVlogVO> records = indexVlogVOIPage.getRecords();
            for (IndexVlogVO item : records) {
                String vlogerId = item.getVlogerId();
                String vlogId = item.getVlogId();

                // 查詢判斷用戶點讚過的視頻
                String boole = this.redis.get(BaseInfoProperties.REDIS_USER_LIKE_VLOG + ":" + myId + ":" + vlogId);
                item.setDoILikeThisVlog(!StringUtils.isBlank(boole) && "1".equalsIgnoreCase(boole));

                boolean b = fansService.queryDoIFollowVloger(myId, vlogerId);
                item.setDoIFollowVloger(b); // 必定是true,我關注的博主列表

                // 查詢視頻的點讚總數
                String vlogLikeCount = this.redis.getStr(BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
                if (StringUtils.isNotBlank(vlogLikeCount) && !vlogLikeCount.equalsIgnoreCase("null")) {
                    item.setLikeCounts(Integer.valueOf(vlogLikeCount));
                } else {
                    item.setLikeCounts(0);
                }
            }
            indexVlogVOIPage.setRecords(records);
        }

        /*Map<String,Object> map = new HashMap<>();
        map.put("userId",myId);
        List<IndexVlogVO> myLinkVlogList = this.vlogMapperCustom.getMyFollowVlog(map);*/
        PagedGridResult pagedGridResult = new PagedGridResult();
        pagedGridResult.setRows(indexVlogVOIPage.getRecords());
        pagedGridResult.setPage((int) indexVlogVOIPage.getCurrent());
        pagedGridResult.setTotal(indexVlogVOIPage.getPages());
        pagedGridResult.setRecords(indexVlogVOIPage.getTotal());
        return pagedGridResult;
    }

    /**
     * 查詢我的點讚列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PagedGridResult getMyLinkVlogList(String userId, Integer page, Integer pageSize) {
        IPage<IndexVlogVO> indexVlogVOIPage = this.vlogMapper.selectJoinPage(new Page<IndexVlogVO>(page, pageSize), IndexVlogVO.class, new MPJLambdaWrapper<IndexVlogVO>().selectAs(Vlog::getId, IndexVlogVO::getVlogId).selectAs(Vlog::getVlogerId, IndexVlogVO::getVlogerId).selectAs(Users::getFace, IndexVlogVO::getVlogerFace).selectAs(Users::getNickname, IndexVlogVO::getVlogerName).selectAs(Vlog::getTitle, IndexVlogVO::getContent).selectAs(Vlog::getLikeCounts, IndexVlogVO::getLikeCounts).selectAs(Vlog::getCommentsCounts, IndexVlogVO::getCommentsCounts).selectAs(Vlog::getIsPrivate, IndexVlogVO::getIsPrivate).select(Vlog::getCover, Vlog::getUrl, Vlog::getWidth, Vlog::getHeight).leftJoin(MyLikedVlog.class, MyLikedVlog::getVlogId, Vlog::getId).leftJoin(Users.class, Users::getId, MyLikedVlog::getUserId).eq(true, Users::getId, userId).and(true, (lambdaWrapper) -> lambdaWrapper.eq(true, Vlog::getIsPrivate, YesOrNo.NO.type)).orderBy(true, false, Vlog::getCreatedTime));
        PagedGridResult pagedGridResult = new PagedGridResult();
        pagedGridResult.setRows(indexVlogVOIPage.getRecords());
        pagedGridResult.setPage((int) indexVlogVOIPage.getCurrent());
        pagedGridResult.setTotal(indexVlogVOIPage.getPages());
        pagedGridResult.setRecords(indexVlogVOIPage.getTotal());
        /*Map<String,Object> map = new HashMap<>();
        map.put("userId",userId);
        List<IndexVlogVO> myLinkVlogList = this.vlogMapperCustom.getMyLinkVlogList(map);*/
        return pagedGridResult;
    }

    /**
     * 查询当前点赞数，重新赋值给当前视频
     */
    @Override
    public Integer getVlogBeLikedCounts(String vlogId) {
        // 查詢視頻的點讚總數
        String vlogLikeCount = this.redis.getStr(BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
        if ("null".equalsIgnoreCase(vlogLikeCount)) {
            vlogLikeCount = "0";
        }

        return Integer.valueOf(vlogLikeCount);
    }


    /**
     * 取消点赞
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public void userUnLikeVlog(String userId, String vlogId) {


        int isDel = this.myLikedVlogMapper.delete(new LambdaQueryWrapper<MyLikedVlog>().eq(true, MyLikedVlog::getUserId, userId).eq(true, MyLikedVlog::getVlogId, vlogId));
        if (isDel <= 0) {
            GraceException.display(ResponseStatusEnum.FAILED);
        }

    }

    /**
     * 用户点赞/喜欢的视屏
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public void userLikeVlog(String userId, String vlogId) {
        MyLikedVlog myLikedVlog = MyLikedVlog.builder().id(sid.nextShort()).userId(userId).vlogId(vlogId).build();

        this.myLikedVlogMapper.insert(myLikedVlog);


        // TODO 点赞视频,创建消息,异步解耦
        Vlog vlog = this.vlogMapper.selectById(vlogId);
        BeanMap msgContent = BeanMap.create(vlog);
        msgContent.put("vlogCover", vlog.getCover());
        String json = JSON.toJSONString(
                MessageMo.builder()
                        .fromUserId(userId)
                        .toUserId(vlog.getVlogerId())
                        .msgType(MessageEnum.LIKE_VLOG.type)
                        .msgContent(msgContent).build());
        this.rabbitTemplate.convertAndSend(
                RabbitMQConfig.EXCHANGE_MSG,
                "routing.sys.msg." + MessageEnum.LIKE_VLOG.enValue,
                json);

    }

    // 查询我的视频列表
    @Override
    public PagedGridResult queryMyVlogList(String userId, Integer page, Integer pageSize, Integer yesOrNo) {

        Page<Vlog> vlogPage = this.vlogMapper.selectPage(new Page<>(page, pageSize), new LambdaQueryWrapper<Vlog>().eq(true, Vlog::getVlogerId, userId).eq(true, Vlog::getIsPrivate, yesOrNo));

        PagedGridResult pagedGridResult = new PagedGridResult();
        pagedGridResult.setRows(vlogPage.getRecords());
        pagedGridResult.setPage((int) vlogPage.getCurrent());
        pagedGridResult.setTotal(vlogPage.getPages());
        pagedGridResult.setRecords(vlogPage.getTotal());
        return pagedGridResult;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public void changeToPrivateOrPublic(String userId, String vlogId, Integer yesOrNo) {

        int isUpdate = this.vlogMapper.update(null, new LambdaUpdateWrapper<Vlog>().eq(true, Vlog::getId, vlogId).eq(true, Vlog::getVlogerId, userId).set(true, Vlog::getIsPrivate, yesOrNo));
        if (isUpdate <= 0) {
            GraceException.display(ResponseStatusEnum.FAILED);
        }
    }


    // 根据视频id查询Vlog
    @Override
    public IndexVlogVO getVlogDetailById(String userId, String vlogId) {

        IndexVlogVO indexVlogVO = this.vlogMapper.selectJoinOne(IndexVlogVO.class, new MPJLambdaWrapper<IndexVlogVO>().selectAll(Vlog.class).selectAs(Vlog::getId, IndexVlogVO::getVlogId).selectAs(Users::getNickname, IndexVlogVO::getVlogerName).selectAs(Users::getFace, IndexVlogVO::getVlogerFace).leftJoin(Users.class, Users::getId, Vlog::getVlogerId).eq(true, Vlog::getId, vlogId));

        if (!ObjectUtils.isEmpty(indexVlogVO)) {
            return indexVlogVO;

        }
      /*  Map<String, Object> map = new HashMap<>();
        map.put("vlogId",vlogId);
        List<IndexVlogVO> list = vlogMapperCustom.getVlogDetailById(map);
        if(!CollectionUtils.isEmpty(list)){
            return list.get(0);
        }*/

        return null;
    }

    // 首页查询
    @Override
    public PagedGridResult getIndexVlogList(String searchKeywords, String userId, Integer page, Integer pageSize) {
        IPage<IndexVlogVO> indexVlogVOIPage = this.vlogMapper.selectJoinPage(new Page<>(page, pageSize),
                IndexVlogVO.class,
                new MPJLambdaWrapper<IndexVlogVO>()
                        .selectAll(Vlog.class)
                        .selectAs(Vlog::getId, IndexVlogVO::getVlogId)
                        .selectAs(Users::getNickname, IndexVlogVO::getVlogerName)
                        .selectAs(Users::getFace, IndexVlogVO::getVlogerFace)
                        .leftJoin(Users.class, Users::getId, Vlog::getVlogerId)
                        .eq(Vlog::getIsPrivate, YesOrNo.NO.type)
                        .and(true, (v -> v.like(Vlog::getTitle, searchKeywords)))
                        .orderBy(true, false, Vlog::getCreatedTime));
        // 判斷是否有點讚的視頻
        if (StringUtils.isNotBlank(userId)) {
            List<IndexVlogVO> records = indexVlogVOIPage.getRecords();
            for (IndexVlogVO item : records) {
                String vlogId = item.getVlogId();

                // 查詢判斷用戶點讚過的視頻
                String boole = this.redis.get(BaseInfoProperties.REDIS_USER_LIKE_VLOG + ":" + userId + ":" + vlogId);
                item.setDoILikeThisVlog(!StringUtils.isBlank(boole) && "1".equalsIgnoreCase(boole));

                // 查詢視頻的點讚總數
                String vlogLikeCount = this.redis.getStr(BaseInfoProperties.REDIS_VLOG_BE_LIKED_COUNTS + ":" + vlogId);
                if (StringUtils.isNotBlank(vlogLikeCount) && !vlogLikeCount.equalsIgnoreCase("null")) {
                    item.setLikeCounts(Integer.valueOf(vlogLikeCount));
                } else {
                    item.setLikeCounts(0);
                }
            }
            indexVlogVOIPage.setRecords(records);
        }
        PagedGridResult pagedGridResult = new PagedGridResult();
        pagedGridResult.setRows(indexVlogVOIPage.getRecords());
        pagedGridResult.setPage((int) indexVlogVOIPage.getCurrent());
        pagedGridResult.setTotal(indexVlogVOIPage.getPages());
        pagedGridResult.setRecords(indexVlogVOIPage.getTotal());

        return pagedGridResult;
    }


    // 新增视频
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public void createVlog(VlogBo vlogBo) {
        Vlog vlog = VlogBo.convertVlog(vlogBo);
        vlog.setId(this.sid.nextShort()).setUpdatedTime(LocalDateTime.now());
        this.vlogMapper.insert(vlog);
    }


}




